//
// Created by Yun on 2025/2/14.
//

#include "bsp_spi.h"

uint8_t Bsp_Spi_Init(const void* pSpiHwCfg)
{
    if(pSpiHwCfg == NULL) return BSP_ERROR;
    Spi_Hw_Cfg_TypeDef *pstHwCfg = (Spi_Hw_Cfg_TypeDef*)pSpiHwCfg;

    // 使能SPI时钟
    if     (pstHwCfg->stHSpi.Instance == SPI1)  __HAL_RCC_SPI1_CLK_ENABLE();
    else if(pstHwCfg->stHSpi.Instance == SPI2)  __HAL_RCC_SPI2_CLK_ENABLE();
    else if(pstHwCfg->stHSpi.Instance == SPI3)  __HAL_RCC_SPI3_CLK_ENABLE();
    else                                        return BSP_ERROR;

    // 初始化GPIO
    if(Bsp_Gpio_Init(&pstHwCfg->stCLK) != BSP_OK) return BSP_ERROR;
    if(Bsp_Gpio_Init(&pstHwCfg->stMOSI) != BSP_OK) return BSP_ERROR;
    if(Bsp_Gpio_Init(&pstHwCfg->stMISO) != BSP_OK) return BSP_ERROR;
    if(pstHwCfg->stHSpi.Init.NSS != SPI_NSS_SOFT) {
        if (Bsp_Gpio_Init(&pstHwCfg->stNSS) != BSP_OK) return BSP_ERROR;
    }
    else {
        if (Bsp_Gpio_Init(&pstHwCfg->stCS) != BSP_OK) return BSP_ERROR;
    }
    // 初始化SPI
    if(HAL_SPI_Init(&pstHwCfg->stHSpi) != HAL_OK) return BSP_ERROR;

    return BSP_OK;
}

uint8_t Bsp_Spi_Transmit(const void* pSpiHwCfg, uint8_t* pu8TxData, uint16_t u16Len, uint32_t u32TimeOut)
{
    if(pSpiHwCfg == NULL) return BSP_ERROR;
    Spi_Hw_Cfg_TypeDef *pstHwCfg = (Spi_Hw_Cfg_TypeDef*)pSpiHwCfg;
    if(HAL_SPI_Transmit(&pstHwCfg->stHSpi, pu8TxData, u16Len, u32TimeOut) != HAL_OK) return BSP_ERROR;
    return BSP_OK;
}

uint8_t Bsp_Spi_Receive (const void* pSpiHwCfg, uint8_t* pu8RxData, uint16_t u16Len, uint32_t u32TimeOut)
{
    if(pSpiHwCfg == NULL) return BSP_ERROR;
    Spi_Hw_Cfg_TypeDef *pstHwCfg = (Spi_Hw_Cfg_TypeDef*)pSpiHwCfg;
    if(HAL_SPI_Receive(&pstHwCfg->stHSpi, pu8RxData, u16Len, u32TimeOut) != HAL_OK) return BSP_ERROR;
    return BSP_OK;
}

uint8_t Bsp_Spi_TransmitReceive(const void* pSpiHwCfg, uint8_t* pu8TxData, uint8_t* pu8RxData, uint16_t u16Len, uint32_t u32TimeOut)
{
    if(pSpiHwCfg == NULL) return BSP_ERROR;
    Spi_Hw_Cfg_TypeDef *pstHwCfg = (Spi_Hw_Cfg_TypeDef*)pSpiHwCfg;
    if(HAL_SPI_TransmitReceive(&pstHwCfg->stHSpi, pu8TxData, pu8RxData, u16Len, u32TimeOut) != HAL_OK) return BSP_ERROR;
    return BSP_OK;
}

uint8_t Bsp_Spi_ControlCS(const void* pSpiHwCfg, uint8_t u8State)
{
    if(pSpiHwCfg == NULL) return BSP_ERROR;
    Spi_Hw_Cfg_TypeDef *pstHwCfg = (Spi_Hw_Cfg_TypeDef*)pSpiHwCfg;

    if(pstHwCfg->stHSpi.Init.NSS != SPI_NSS_SOFT) return BSP_ERROR;
    return Bsp_Gpio_Write(&pstHwCfg->stCS, u8State);
}

Spi_Interface_TypeDef stBspSpiInterface = {
    .Init               = Bsp_Spi_Init,
    .Transmit           = Bsp_Spi_Transmit,
    .Receive            = Bsp_Spi_Receive,
    .TransmitReceive    = Bsp_Spi_TransmitReceive,
    .ControlCS          = Bsp_Spi_ControlCS,
};
